package h2.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * H2服务器配置类，负责加载和管理所有配置参数
 */
public class H2ServerConfig {
    // 默认配置参数
    private static final String DEFAULT_PROPERTIES_FILE = "h2-server.properties";
    private static final int DEFAULT_TCP_PORT = 9092;
    private static final String DEFAULT_DB_NAME = "appdb";
    private static final String DEFAULT_DB_PATH = System.getProperty("user.home") + File.separator + "h2data";
    private static final boolean DEFAULT_ALLOW_REMOTE = false;
    private static final boolean DEFAULT_SSL_ENABLED = true;
    private static final int DEFAULT_MAX_CONNECTIONS = 50;
    private static final int DEFAULT_CONNECTION_TIMEOUT = 30000;

    // 配置参数
    private int tcpPort;
    private String dbName;
    private String dbPath;
    private String adminUser;
    private String adminPassword;
    private String readerUser;
    private String readerPassword;
    private boolean allowRemote;
    private boolean sslEnabled;
    private String keystorePath;
    private String keystorePassword;
    private int maxConnections;
    private int connectionTimeout;

    /**
     * 从默认配置文件加载配置
     */
    public H2ServerConfig() {
        this(DEFAULT_PROPERTIES_FILE);
    }

    /**
     * 从指定配置文件加载配置
     */
    public H2ServerConfig(String configFilePath) {
        // 加载默认配置
        loadDefaults();

        // 加载配置文件
        loadFromFile(configFilePath);

        // 从系统环境变量覆盖配置（便于容器化部署）
        loadFromEnvironment();

        // 确保数据库目录存在
        ensureDbDirectoryExists();
    }

    private void loadDefaults() {
        this.tcpPort = DEFAULT_TCP_PORT;
        this.dbName = DEFAULT_DB_NAME;
        this.dbPath = DEFAULT_DB_PATH;
        this.allowRemote = DEFAULT_ALLOW_REMOTE;
        this.sslEnabled = DEFAULT_SSL_ENABLED;
        this.maxConnections = DEFAULT_MAX_CONNECTIONS;
        this.connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
    }

    private void loadFromFile(String configFilePath) {
        File configFile = new File(configFilePath);
        if (configFile.exists() && configFile.canRead()) {
            try (FileInputStream fis = new FileInputStream(configFile)) {
                Properties props = new Properties();
                props.load(fis);

                // 读取配置参数
                this.tcpPort = getIntProperty(props, "h2.tcp.port", DEFAULT_TCP_PORT);
                this.dbName = props.getProperty("h2.db.name", DEFAULT_DB_NAME);
                this.dbPath = props.getProperty("h2.db.path", DEFAULT_DB_PATH);
                this.adminUser = props.getProperty("h2.admin.user", "admin");
                this.adminPassword = props.getProperty("h2.admin.password");
                this.readerUser = props.getProperty("h2.reader.user", "reader");
                this.readerPassword = props.getProperty("h2.reader.password", "readOnly123");
                this.allowRemote = getBooleanProperty(props, "h2.allow.remote", DEFAULT_ALLOW_REMOTE);
                this.sslEnabled = getBooleanProperty(props, "h2.ssl.enabled", DEFAULT_SSL_ENABLED);
                this.keystorePath = props.getProperty("h2.ssl.keystore.path", "h2.keystore");
                this.keystorePassword = props.getProperty("h2.ssl.keystore.password");
                this.maxConnections = getIntProperty(props, "h2.max.connections", DEFAULT_MAX_CONNECTIONS);
                this.connectionTimeout = getIntProperty(props, "h2.connection.timeout", DEFAULT_CONNECTION_TIMEOUT);

                System.out.println("成功加载配置文件: " + configFilePath);
            } catch (IOException e) {
                System.err.println("加载配置文件失败，使用默认配置: " + e.getMessage());
            }
        } else {
            System.out.println("配置文件不存在，使用默认配置: " + configFilePath);
        }
    }

    private void loadFromEnvironment() {
        // 从环境变量读取敏感信息，优先于配置文件
        this.adminPassword = System.getenv("H2_ADMIN_PASSWORD") != null ?
                System.getenv("H2_ADMIN_PASSWORD") : this.adminPassword;
        this.keystorePassword = System.getenv("H2_KEYSTORE_PASSWORD") != null ?
                System.getenv("H2_KEYSTORE_PASSWORD") : this.keystorePassword;
    }

    private void ensureDbDirectoryExists() {
        File dbDir = new File(dbPath);
        if (!dbDir.exists()) {
            if (dbDir.mkdirs()) {
                System.out.println("创建数据库目录: " + dbPath);
            } else {
                System.err.println("创建数据库目录失败: " + dbPath);
            }
        }
    }

    // 工具方法：获取整数类型配置
    private int getIntProperty(Properties props, String key, int defaultValue) {
        try {
            String value = props.getProperty(key);
            return value != null ? Integer.parseInt(value) : defaultValue;
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    // 工具方法：获取布尔类型配置
    private boolean getBooleanProperty(Properties props, String key, boolean defaultValue) {
        String value = props.getProperty(key);
        return value != null ? Boolean.parseBoolean(value) : defaultValue;
    }

    // Getter方法
    public int getTcpPort() {
        return tcpPort;
    }

    public String getDbName() {
        return dbName;
    }

    public String getDbPath() {
        return dbPath;
    }

    public String getAdminUser() {
        return adminUser;
    }

    public String getAdminPassword() {
        return adminPassword;
    }

    public String getReaderUser() {
        return readerUser;
    }

    public String getReaderPassword() {
        return readerPassword;
    }

    public boolean isAllowRemote() {
        return allowRemote;
    }

    public boolean isSslEnabled() {
        return sslEnabled;
    }

    public String getKeystorePath() {
        return keystorePath;
    }

    public String getKeystorePassword() {
        return keystorePassword;
    }

    public int getMaxConnections() {
        return maxConnections;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    // 获取完整数据库URL
    public String getJdbcUrl() {
        return String.format("jdbc:h2:tcp://localhost:%d/%s/%s%s",
                tcpPort,
                dbPath,
                dbName,
                sslEnabled ? ";SSL=true" : "");
    }
}
    